package cn.billy.user.service.impl;

import cn.billy.basic.constant.BaseConstants;
import cn.billy.basic.dto.RegisterDto;
import cn.billy.basic.exception.BusinessException;
import cn.billy.basic.utils.MD5Utils;
import cn.billy.basic.utils.StrUtils;
import cn.billy.user.domain.Logininfo;
import cn.billy.user.domain.User;
import cn.billy.user.mapper.LogininfoMapper;
import cn.billy.user.mapper.UserMapper;
import cn.billy.user.service.IUserService;
import cn.billy.basic.service.impl.BaseServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author billy
 * @since 2022-07-06
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {

    @Autowired
    private RedisTemplate redisTemplate;
    


    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LogininfoMapper logininfoMapper;

    @Override
    public void phoneCodeRegister(RegisterDto registerDto) {
//      1.非空判断
        String phone = registerDto.getPhone();
        String password = registerDto.getPassword();
        String confirmPassword = registerDto.getConfirmPassword();
        String smsCodeValue = registerDto.getSmsCodeValue();
        // 判断参数非空
        if (StringUtils.isEmpty(phone)
                || StringUtils.isEmpty(password)
                || StringUtils.isEmpty(confirmPassword)
                || StringUtils.isEmpty(smsCodeValue)){
            throw new BusinessException("参数错误，请重新输入！");
        }

        if(!registerDto.getPassword().equals(registerDto.getConfirmPassword())){
            throw new BusinessException("两次秘密不一致，请重新输入");
        }
//    2.判断两次手机号是否一致，业务键+手机号拼接后去Redis中获取value，如果没有，说明要么不一致，要么过期了，那就提示重新获取
        String smsCodeKey = BaseConstants.VerifyCodeConstant.BUSINESS_REGISTER_PREFIX + phone;
        Object smsCodeValueTmp = redisTemplate.opsForValue().get(smsCodeKey);
        if (smsCodeValueTmp == null){
            throw new BusinessException("验证码已过期，请稍后再试");
        }
        String[] split = smsCodeValueTmp.toString().split(":");
        String smsCode = split[1];
        if (!smsCode.equalsIgnoreCase(smsCodeValue)){
            throw new BusinessException("验证码错误，请重新输入");
        }
        User user = registerDto2User(registerDto);
        Logininfo logininfo = user2Logininfo(user);
        logininfoMapper.add(logininfo);
        user.setLogininfoId(logininfo.getId());
        userMapper.add(user);



//    1.要么手机号不对
//    2.要么过期了
//    3.要么验证码错误
//    3.判断两次密码是否一致
//    4.根据手机号查询数据库是否存在此用户
//    5.初始化用户对象，设置盐值设置密码，设置状态为1
//    6.拷贝user对象到logininfo对象中，保存logininfo
//    7.设置logininfo的id到user的logininfo_id字段，进行修改
    }

    @Override
    public void registerEmail(RegisterDto registerDto) {
        // 非空判断
        String email = registerDto.getEmail();
        System.out.println("email:"+email);
        String emailImageCodeValue = registerDto.getEmailImageCodeValue();
        String password = registerDto.getPassword();
        String emailCode = registerDto.getEmailCode();
        String confirmPassword = registerDto.getConfirmPassword();
        if (email == null){
            throw new BusinessException("邮箱名不能为空！");
        }
        if (emailImageCodeValue == null){
            throw new BusinessException("图片验证码不能为空！");
        }
        if (emailCode == null){
            throw new BusinessException("邮箱验证码不能为空！");
        }
        if (password == null){
            throw new BusinessException("密码不能为空！");
        }
        if (confirmPassword == null){
            throw new BusinessException("请确认密码");
        }
        // 两次密码校验
        if (!confirmPassword.equals(password)){
            throw new BusinessException("两次密码填写不一致，请重新填写");
        }
        // 获取redis中的key
        String emailCodeKey = BaseConstants.VerifyCodeConstant.BUSINESS_REGISTER_PREFIX + email;
        Object emailCodeValueTmp = redisTemplate.opsForValue().get(emailCodeKey);
        // 邮箱验证码在Redis中不存在处理
        if (emailCodeValueTmp == null){
            throw new BusinessException("验证码已过期，请重新获取");
        }
        String[] split = emailCodeValueTmp.toString().split(":");
        String emailCodeValue = split[1];

        // 判断验证码是否正确
        if (!emailCodeValue.equalsIgnoreCase(emailCode)){
            throw new BusinessException("验证码输出错误，请重新输入");
        }

        User user = registerDto2User(registerDto);
        System.out.println("22222222:"+user);
        userMapper.add(user);

        Logininfo logininfo = user2Logininfo(user);
        logininfoMapper.add(logininfo);

        user.setLogininfoId(logininfo.getId());
        userMapper.update(user);
    }

    @Override
    public User getByLogininfoId(Long id) {
        return userMapper.getByLogininfoId(id);
    }

    private Logininfo user2Logininfo(User user) {
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(user,logininfo);
        logininfo.setType(1);
        return logininfo;

    }

    private User registerDto2User(RegisterDto registerDto) {
        User user = new User();
        String email = registerDto.getEmail();
        user.setEmail(email);
        user.setUsername(registerDto.getPhone());
        user.setPhone(registerDto.getPhone());
        String salt = StrUtils.getComplexRandomString(32);
        String md5pwd = MD5Utils.encrypByMd5(registerDto.getPassword() + salt);
        user.setSalt(salt);
        user.setPassword(md5pwd);
        return user;
    }

    @Override
    @Transactional
    public void update(User user) {
        Long logininfoId = user.getLogininfoId();
        // 查询数据库中的的user
        User nowUser = userMapper.getById(user.getId());
        // 获取当前对象的user对象密码
        String password = user.getPassword();
        // 获取数据库中user对象的盐值和密码
        String salt = nowUser.getSalt();
        String oldPassword = nowUser.getPassword();
        // 判断用户是否修改密码
        String nowPassword = MD5Utils.encrypByMd5(salt + password);
        if (!oldPassword.equals(nowPassword)){
            // 随机生成新的盐值
            String newSalt = StrUtils.getComplexRandomString(32);
            // 调用MD5共具类进行加密，然后生成新的加密后的密码
            String newPassword = MD5Utils.encrypByMd5(newSalt + password);
            //将新的盐值和密码设置进去
            user.setSalt(newSalt);
            user.setPassword(newPassword);
        }
        // 根据user的logininfoId查询出数据库中的logininfo对象
        Logininfo logininfo = logininfoMapper.getById(logininfoId);
        // 将前端传入的user对象覆盖掉数据库中的logininfo对象
        BeanUtils.copyProperties(user,logininfo);
        logininfo.setId(logininfoId);
        // 将logininfo的类型设置为1，表示是用户
        logininfo.setType(1);
        // 调用修改方法进行修改
        userMapper.update(user);
        logininfoMapper.update(logininfo);
    }

    @Override
    public void remove(Long id) {
        // 根据id查询到user的数据
        User byId = userMapper.getById(id);
        // 然后再拿出logininfoId
        Long logininfoId = byId.getLogininfoId();
        // 直接调用删除方法，把相对应的id传进去
        userMapper.remove(id);
        logininfoMapper.remove(logininfoId);
    }
}
